package org.framework.lazy.cloud.network.heartbeat.protocol.advanced;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.payload.NettyProxyMsg;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.payload.NettyChannelContext;
import org.framework.lazy.cloud.network.heartbeat.common.advanced.proxy.http.AbstractHttpLocalProxyTypeAdvanced;
import org.framework.lazy.cloud.network.heartbeat.common.decoder.TransferDecoder;
import org.framework.lazy.cloud.network.heartbeat.common.encoder.TransferEncoder;
import org.framework.lazy.cloud.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import org.framework.lazy.cloud.network.heartbeat.protocol.handler.NettyHttpProxyBackendHandler;
import org.springframework.stereotype.Component;

/**
 * http 本地代理
 */
@Component
public class HttpProtocolHandleChannelLocalProxyTypeAdvanced extends AbstractHttpLocalProxyTypeAdvanced<NettyProxyMsg> {


    /**
     * 处理当前数据
     *
     * @param nettyChannelContext       当前通道
     * @param nettyProxyMsg 通道数据
     */
    @Override
    protected void doHandler(NettyChannelContext nettyChannelContext, NettyProxyMsg nettyProxyMsg) {
        String targetPortString = nettyProxyMsg.getTargetPortString();
        String targetIpString = nettyProxyMsg.getTargetIpString();
        Bootstrap b = new Bootstrap();
        Channel channel = nettyChannelContext.channel();
        b.group(channel.eventLoop())
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(
                                new TransferDecoder(Integer.MAX_VALUE, 1024 * 1024 * 10),
                                new TransferEncoder(),
                                new NettyHttpProxyBackendHandler()
                        );
                    }
                });
        ChannelFuture f = b.connect(targetIpString, Integer.parseInt(targetPortString));
        Channel proxyChannel = f.channel();
        f.addListener((ChannelFutureListener) future -> {
            if (future.isSuccess()) {
                ChannelAttributeKeyUtils.buildNextChannel(proxyChannel, channel);
                ChannelAttributeKeyUtils.buildNextChannel(channel, proxyChannel);
                ByteBuf buf = channel.config().getAllocator().buffer(nettyProxyMsg.getData().length);
                buf.writeBytes(nettyProxyMsg.getData());
                proxyChannel.writeAndFlush(buf);
            } else {
                channel.close();
            }
        });
    }
}
